import { resolve } from 'node:path'
import { loadEnv } from 'vite'
import vueJsx from '@vitejs/plugin-vue-jsx'
import vue from '@vitejs/plugin-vue'
import checker from 'vite-plugin-checker'
import Components from 'unplugin-vue-components/vite'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
import Unocss from 'unocss/vite'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import dayjs from 'dayjs'
import pkg from './package.json'
import type { UserConfig, ConfigEnv } from 'vite'
import { parse as parseImports } from 'es-module-lexer'
import MagicString from 'magic-string'
import fs from 'fs'
import path from 'path'
import { GetModuleInfo } from 'rollup'
const CWD = process.cwd()

function readDirRecursive(dirPath: string, fileList: string[] = []): string[] {
  const files = fs.readdirSync(dirPath)

  files.forEach(file => {
    const filePath = path.relative(CWD, path.join(dirPath, file)) as string
    const fileStat = fs.statSync(filePath)

    if (fileStat.isDirectory()) {
      readDirRecursive(filePath, fileList)
    } else {
      fileList.push(path.normalize(filePath))
    }
  })

  return fileList
}
let arr: any = []
const __APP_INFO__ = {
  pkg,
  lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
}
const chunkGroups: { [key: string]: string[] } = {
  'vue-vendor': [import.meta.resolve('vue')],
}
let comp_utils_map = new Map()
// comp -> utils
// function isDepInclude(
//   id: string,
//   importChain: string[],
//   getModuleInfo: GetModuleInfo,
// ): boolean | undefined {
//   if (importChain.includes(id)) return false

//   const moduleInfo = getModuleInfo(id)
//   let importers = moduleInfo?.importers
//   if (!moduleInfo || !importers) {
//     return true
//   }

//   return importers.every(item => isDepInclude(item, importChain.concat(id), getModuleInfo))

//   // const moduleInfo = getModuleInfo(id)
//   // if (!moduleInfo || !moduleInfo.importers) {
//   //   return false
//   // }
//   // if (moduleInfo.importers.length === 0 && !importChain.includes(id)) {
//   //   return true
//   // }
//   // const isInclude = moduleInfo.importers.some((importer: any) =>
//   //   isDepInclude(importer, importChain.concat(id), getModuleInfo),
//   // )
//   // return isInclude
// }
const cache = new Map();

function isDepInclude (id: string, depPaths: string[], importChain: string[], getModuleInfo:any): boolean | undefined  {
  const key = `${id}-${depPaths.join('|')}`;
  // 出现循环依赖，不考虑
  if (importChain.includes(id)) {
    cache.set(key, false);
    return false;
  }
  // 验证缓存
  if (cache.has(key)) {
    return cache.get(key);
  }
  // 命中依赖列表
  if (depPaths.includes(id)) {
    // 引用链中的文件都记录到缓存中
    importChain.forEach(item => cache.set(`${item}-${depPaths.join('|')}`, true));
    return true;
  }
  const moduleInfo = getModuleInfo(id);
  if (!moduleInfo || !moduleInfo.importers) {
    cache.set(key, false);
    return false;
  }
  // 核心逻辑，递归查找上层引用者
  const isInclude = moduleInfo.importers.some(
    (importer:any) => isDepInclude(importer, depPaths, importChain.concat(id), getModuleInfo)
  );
  // 设置缓存
  cache.set(key, isInclude);
  return isInclude;
};
export default ({ command, mode }: ConfigEnv): UserConfig => {
  // 环境变量
  const { VITE_BASE_URL, VITE_DROP_CONSOLE } = loadEnv(mode, CWD)

  const isDev = command === 'serve'

  return {
    base: VITE_BASE_URL,
    define: {
      __APP_INFO__: JSON.stringify(__APP_INFO__),
    },
    resolve: {
      alias: [
        {
          find: '@',
          replacement: resolve(__dirname, './src'),
        },
      ],
    },
    plugins: [
      vue(),
      Unocss(),
      vueJsx({
        // options are passed on to @vue/babel-plugin-jsx
      }),
      createSvgIconsPlugin({
        iconDirs: [resolve(CWD, 'src/assets/icons')],
        symbolId: 'svg-icon-[dir]-[name]',
      }),
      Components({
        dts: 'types/components.d.ts',
        types: [
          {
            from: './src/components/basic/button/',
            names: ['AButton'],
          },
          {
            from: 'vue-router',
            names: ['RouterLink', 'RouterView'],
          },
        ],
        resolvers: [
          AntDesignVueResolver({
            importStyle: false,
            exclude: ['Button'],
          }),
        ],
      }),
      isDev &&
        checker({
          typescript: true,
          eslint: {
            useFlatConfig: true,
            lintCommand: 'eslint "./src/**/*.{.vue,ts,tsx}"',
          },
          overlay: {
            initialIsOpen: false,
          },
        }),
      // {
      //   name: 'viteChunkName',
      //   async transform(source, id) {
      //     if (!id.includes('node_modules')) {
      //       const routeChunkNameRE = /((webpackC|c)hunkName)|viteChunk:\s*["']([\w-/.]+)["']/
      //       if (routeChunkNameRE) {

      //         console.log(source)
      //         const [imports] = parseImports(source);
      //         console.log("hello world")
      //       }
      //     }
      //   },
      // },
    ],
    css: {
      preprocessorOptions: {
        less: {
          javascriptEnabled: true,
          modifyVars: {},
        },
      },
    },
    server: {
      host: '0.0.0.0',
      port: 7002,
      open: false,
      warmup: {
        clientFiles: ['./index.html', './src/{components,api}/*'],
      },
    },
    optimizeDeps: {
      include: [
        'lodash-es',
        'echarts',
        'ant-design-vue/es/locale/zh_CN',
        'ant-design-vue/es/locale/en_US',
      ],
    },
    esbuild: {
      pure: VITE_DROP_CONSOLE === 'true' ? ['console.log', 'debugger'] : [],
      supported: {
        'top-level-await': true,
      },
    },
    build: {
      minify: 'esbuild',
      cssTarget: 'chrome89',
      chunkSizeWarningLimit: 2000,
      rollupOptions: {
        output: {
          manualChunks(id, { getModuleInfo }) {
            // for (const group of Object.keys(chunkGroups)) {
            let reg = /\/src\/(components)\/([^/]+\/)*[^/]+\.(vue|ts|tsx|js|jsx)$/
            //  const viteChunkMatch = id.match(reg)

            if (!id.includes('node_modules')) {
              if (/\/src\/(components)|(utils)\//.test(id)) {
                // console.log(isDepInclude(id, [], getModuleInfo))

                let isDep = isDepInclude(id,[], [], getModuleInfo)
                if (id.includes('src/components/') && isDep) {
                  return 'comp_chunk'
                } else if (id.includes('src/utils/') && isDep) {
                  return 'utils_chunk'
                } else {
                  return 'bind-chunk'
                }

                // if (isDepInclude(id, [], getModuleInfo)) {
                //   return 'bind-chunk'
                // }
              }

              // if (
              //   /\/src\/(utils)\/([^/]+\/)*[^/]+\.(vue|ts|tsx|js|jsx)$/.test(id)
              // ) {
              //   return 'utils_Chunk'
              // }
            }

            if (id.includes('/src/locales/helper.ts')) {
              return 'antdv'
            } else if (id.includes('node_modules/ant-design-vue/')) {
              return 'antdv'
            } else if (/node_modules\/(vue|vue-router|pinia)\//.test(id)) {
              return 'vue'
            }
          },
        },
        onwarn(warning, rollupWarn) {
          if (
            warning.code === 'CYCLIC_CROSS_CHUNK_REEXPORT' &&
            warning.exporter?.includes('src/api/')
          ) {
            return
          }
          rollupWarn(warning)
        },
      },
    },
  }
}
